package com.quick.mq.config;
import com.quick.common.Component.ExchangeType;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class MQConfig {

    // 叫车请求队列（用户发起叫车）
    @Bean
    public Queue callCarQueue() {
        return QueueBuilder.durable("call_car_queue")
                .withArgument("x-dead-letter-exchange", "dlx.exchange")  // 核心：指定死信交换机（消息成为死信后，发送到该交换机）
                .withArgument("x-dead-letter-routing-key", "dlx.routing.key")   // 核心：指定死信路由键（死信交换机通过该路由键转发到死信队列）
                .withArgument("x-message-ttl", 60000)   //消息过期时间(60秒未处理放入死信队列，单位毫秒)
                .withArgument("x-max-length", 200)    //最长队列长度，超过长度放入死信队列
                .build();
    }

    // 待派单队列（系统生成的待派单）
    @Bean
    public Queue waitOrderQueue() {
        return QueueBuilder.durable("wait_order_queue")
                .withArgument("x-dead-letter-exchange", "dlx.exchange")
                .withArgument("x-dead-letter-routing-key", "dlx.routing.key")
                .withArgument("x-message-ttl", 60000)
                .withArgument("x-max-length", 200)
                .build();
    }
    //派单队列
    @Bean
    public Queue dispatchOrderQueue() {
        return QueueBuilder.durable("dispatch_order_queue")
                .withArgument("x-dead-letter-exchange", "dlx.exchange")
                .withArgument("x-dead-letter-routing-key", "dlx.routing.key")
                .withArgument("x-message-ttl", 60000)
                .withArgument("x-max-length", 200)
                .build();
    }

    //死信队列
    @Bean
    public Queue deadLetterQueue() {
        return QueueBuilder.durable("dead_letter_queue").build();
    }

    // 订单状态变更-用户通知队列（给用户发推送）
    @Bean
    public Queue userNotifyQueue() {
        return new Queue("user_notify_queue");
    }

    // 订单状态变更-司机通知队列（给司机发推送）
    @Bean
    public Queue driverNotifyQueue() {
        return new Queue("driver_notify_queue");
    }


    // 2. 交换机定义（类型与枚举匹配）
    // 主题交换机（处理叫车、派单等有明确路由关系的消息）
    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange(ExchangeType.topicExchange.toString()); // 正确绑定主题枚举
    }

    //死信交换机
    @Bean
    public DirectExchange deadLetterExchange() {
        return ExchangeBuilder.directExchange("dlx.exchange")
                .durable( true)
                .build();
    }
    // 扇出交换机（处理订单状态变更的广播消息）
    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange(ExchangeType.fanoutExchange.toString());
    }


    // 3. 主题交换机绑定（路由键与队列匹配）
    // 叫车请求队列绑定 "user.call_car"（用户叫车消息路由到这里）
    @Bean
    public Binding binding_Topic_CallCar(@Qualifier("callCarQueue") Queue callCarQueue,@Qualifier("topicExchange") TopicExchange topicExchange) {
        return BindingBuilder.bind(callCarQueue).to(topicExchange).with("call_car.#"); // 路由键规范
    }

    // 待派单队列绑定 "order.wait_order"（待派单消息路由到这里）
    @Bean
    public Binding binding_Topic_WaitOrder(@Qualifier("waitOrderQueue") Queue waitOrderQueue,@Qualifier("topicExchange") TopicExchange topicExchange) {
        return BindingBuilder.bind(waitOrderQueue).to(topicExchange).with("wait_order.#");
    }

    // 派单队列绑定 "dispatch.order_driver"（派单消息路由到这里）
    @Bean
    public Binding binding_Topic_DispatchOrder(@Qualifier("dispatchOrderQueue") Queue dispatchOrderQueue,@Qualifier("topicExchange") TopicExchange topicExchange) {
        return BindingBuilder.bind(dispatchOrderQueue).to(topicExchange).with("dispatch_order.#");
    }
    //死信队列绑定
    @Bean
    public Binding binding_Topic_DeadLetter(@Qualifier("deadLetterQueue") Queue deadLetterQueue,@Qualifier("deadLetterExchange") DirectExchange deadLetterExchange) {
        return BindingBuilder.bind(deadLetterQueue).to(deadLetterExchange).with("dlx.routing.key");
    }

    // 4. 扇出交换机绑定（广播订单状态变更消息到多个队列）

    @Bean
    public Binding binding_Fanout_UserNotify(@Qualifier("userNotifyQueue") Queue userNotifyQueue, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(userNotifyQueue).to(fanoutExchange);
    }

    @Bean
    public Binding binding_Fanout_DriverNotify(@Qualifier("driverNotifyQueue") Queue driverNotifyQueue, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(driverNotifyQueue).to(fanoutExchange);
    }

    // 配置RabbitTemplate，开启确认机制和返回回调
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);

        // 1. 开启发布确认（确认消息是否到达交换机）
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                System.out.println("消息已成功到达交换机：" + correlationData);
            } else {
                System.err.println("消息未到达交换机，原因：" + cause); // 关键：捕获交换机不存在等问题
            }
        });

        // 2. 开启返回回调（确认消息到达交换机但无法路由到队列）
        rabbitTemplate.setMandatory(true); // 必须设为true，否则不会触发返回回调
        rabbitTemplate.setReturnsCallback(returned -> {
            System.err.println("消息到达交换机但无法路由：" +
                    "交换机=" + returned.getExchange() +
                    "，路由键=" + returned.getRoutingKey() +
                    "，原因=" + returned.getReplyText());
        });

        return rabbitTemplate;
    }
}